/////////////////
// ddhelper.js //
/////////////////////////
// Version: 2002.05.31 //
/////////////////////////
// This file is used as an interface into 
// Anthony's famous DragDrop.js file.  The functions
// defined in this file should act as the page programmer's
// sole drag and drop interface (none of the 
// dragdrop.js functions or variables should be accessed
// directly by the pages).
//
// If you want to use this code to create a drag and drop
// page, you need to do the following;
// 1) Create your drag layers, naming them
//    DragLayer1, DragLayer2, ....
// 2) Create your drop target layers, naming them
//    DropTarget1, DropTarget2, ....
// 3) Place a call to DDH_initDragDrop(frameWidth, frameHeight, correctJS, incorrectJS, missJS)
//    somewhere in your souce code so that it gets called
//    right after the page loads.  correctJS, incorrectJS,
//    missJS are strings representing the JavaScript code
//    that you want called when a drag item is dropped
//    on a correct target, an incorrect target, or missed
//    all targets.  frameWidth and frameHeight specify
//    the width and height of the frame. These numbers will
//    be used to constrict the drag movement to prevent
//    users from dragging outside the frame boundry.
// 4) Place calls to DDH_setTargets() to specify the
//    valid landing areas for each drag item.  For
//    example:
//
//        DDH_setTargets(1,5,8,9,10,11);
//
//    This call sets layers "DropTarget5", "DropTarget8"
//    "DropTarget9", "DropTarget10" and "DropTarget11"
//    as valid landing areas for layer "DragLayer1".  If
//    "DragLayer1" lands on any other drop target, it
//    will be treated as a miss, and the missJS code
//    specified in the call to DDH_initDragDrop() will
//    be executed.
// 5) Place calls to DDH_setCorrectTargets() to specify
//    the correct landing areas for a drag layer.  For
//    example:
//
//        DDH_setCorrectTargets(7,5,11);
//
//    This call sets layers "DropTarget5" and "DropTarget11"
//    as correct landing areas for layer "DragLayer1".  If
//    "DragLayer1" is dropped on one of these layers, the
//    correctJS code specified in the call to DDH_initDragDrop()
//    will be executed.  If "DragLayer1" is dropped on any other
//    valid target, the incorrectJS code specified in the call
//    to DDH_initDragDrop() will be executed.
// 
// After these 5 steps have been completed, you will
// have a working drag and drop page with the following
// default behaviors:
// - Dragged layers that miss are snapped back to their
//   original positions.
// - Dragged layers that land on any of their valid
//   target layers will stay there (correct or incorrect).
// - The global variable DDH_lastItemDragged will always
//   contain the number of the last layer dragged 
//   (DDH_lastItemDragged equals null initially).
// - The global variable DDH_lastTargetHit will always
//   contain the number of the last layer that had 
//   a drag layer dropped on it (DDH_lastTargetHit equals
//   null after a miss).
//
// Listed below are the full set of functions and global
// variables that page programmers can use to control 
// their drag and drop pages.
//
// int DDH_lastItemDragged
// int DDH_lastTargetHit
//
// void DDH_initDragDrop(int frameWidth, int frameHeight, String correctJS, String incorrectJS, String missJS)
// void DDH_setTargets(int dragLayerNumber, int dropTargetNumber *[, int dropTargetNumber])
// void DDH_setCorrectTargets(int dragLayerNumber, int dropTargetNumber *[, int dropTargetNumber])
// void DDH_clearCorrectTargets(int dragLayerNumber)
// void DDH_disableDragItem(int dragLayerNumber)
// void DDH_disableDragItems(int dragLayerNumber *[, int dragLayerNumber])
// void DDH_enableDragItem(int dragLayerNumber)
// void DDH_enableDragItems(int dragLayerNumber *[, int dragLayerNumber])
// void DDH_disableDropTarget(int dropTargetNumber)
// void DDH_disableDropTargets(int dropTargetNumber *[, int dropTargetNumber])
// void DDH_enableDropTarget(int dropTargetNumber)
// void DDH_enableDropTargets(int dropTargetNumber *[, int dropTargetNumber])
// int DDH_numItemsDropped()
// boolean DDH_dragItemIsDropped(int dragLayerNumber)
// boolean DDH_dragItemIsCorrect(int dragLayerNumber)
// boolean DDH_dropTargetIsOccupied(int dropTargetNumber)
// boolean DDH_dropTargetIsCorrect(int dropTargetNumber)
// int DDH_dropTargetOccupiedCount(int dropTargetNumber)
// void DDH_snapToOrigin(int DragItemNumber)
// void DDH_dragToTarget(int dragItemNumber, int dropTargetNumber, boolean evaluateFlag)
// void DDH_checkDrop(int dragItemNumber)
// string DDH_getOccupiers(int dropTargetNumber)
// void DDH_setHitDistance(int dist)
// int DDH_getOccupies(int DragItemNumber)


var disabledDropTargetArray = new Array();

var DDH_lastItemDragged = null; //integer
var DDH_lastTargetHit = null; // integer

// Initialize Drag Layers and Drop Targets.
function DDH_initDragDrop(width, height, correctJS, incorrectJS, missJS)
{
	DDH_SetFrameDimensions(width, height);
	autoInitDragItems("DDH_Correct('" + correctJS + "')","DDH_Incorrect('" + incorrectJS + "')","DDH_Miss('" + missJS + "')",SNAPBACK_MISS);
	autoInitDropTargets();
	for (var i=0;i<dropTargetArray.length;i++)
	{
		dropTargetArray[i].multiDropEnabled = false;
		disabledDropTargetArray[i] = false;
	}
	clearCorrectTargets();
}

function DDH_setHitDistance(dist)
{
	DRAG_DROP_DISTANCE = dist;
}

function DDH_Correct(js)
{
	if (previousTarget != null && !previousTarget.multiDropEnabled && !disabledDropTargetArray[DDH_getLayerNumber(previousTarget)-1]) 
	{
		previousTarget.enabled = true;
	}
	if (!lastItemDragged.occupies.multiDropEnabled) 
	{
		lastItemDragged.occupies.enabled = false;
	}
	DDH_lastItemDragged = DDH_getLayerNumber(lastItemDragged);
	DDH_lastTargetHit = DDH_getLayerNumber(lastItemDragged.occupies);
	eval(js);
}

function DDH_Incorrect(js)
{
	if (previousTarget != null && !previousTarget.multiDropEnabled && !disabledDropTargetArray[DDH_getLayerNumber(previousTarget)-1]) 
	{
		previousTarget.enabled = true;
	}
	if (!lastItemDragged.occupies.multiDropEnabled)
	{
		lastItemDragged.occupies.enabled = false;
	}
	DDH_lastItemDragged = DDH_getLayerNumber(lastItemDragged);
	DDH_lastTargetHit = DDH_getLayerNumber(lastItemDragged.occupies);
	eval(js);
}

function DDH_Miss(js)
{	
	if (previousTarget != null && !previousTarget.multiDropEnabled && !disabledDropTargetArray[DDH_getLayerNumber(previousTarget)-1]) 
	{
		previousTarget.enabled = true;
	}
	DDH_lastItemDragged = DDH_getLayerNumber(lastItemDragged);
	DDH_lastTargetHit = null;
	eval(js);
}

// Clear correct drop targets for all drag layers.
function clearCorrectTargets()
{
	for (var i=0;i<dragItemArray.length;i++)
	{
		for (var t=0;t<dropTargetArray.length;t++)
		{
			dragItemArray[i].evalMask[t] = false;
		}
	}
}

// Assign a set of target layers to a drag layer.
function DDH_setTargets(dragLayerNumber)
{
	if (DDH_setTargets.arguments.length < 2)
	{
		alert("The function DDH_setTargets(dragLayerNumber *[,dropTargetNumber]) requires 2 or more arguments!");
		return;
	}
	
	dragItemArray[dragLayerNumber-1].targets = new Array();
	dragItemArray[dragLayerNumber-1].evalMask = new Array();
	for (var i=1;i<DDH_setTargets.arguments.length;i++)
	{
		dragItemArray[dragLayerNumber-1].targets[i-1] = dropTargetArray[DDH_setTargets.arguments[i]-1];
		dragItemArray[dragLayerNumber-1].evalMask[i-1] = false;
	}
}

function DDH_clearCorrectTargets(dragLayerNumber)
{
	if (DDH_clearCorrectTargets.arguments.length < 1)
	{
		alert("The function DDH_clearCorrectTargets(dragLayerNumber) requires 1 argument!");
		return;
	}
	
	// Clear all evalMask entries.
	for (var t=0;t<dragItemArray[dragLayerNumber-1].targets.length;t++)
	{
		dragItemArray[dragLayerNumber-1].evalMask[t] = false;
	}
}

// Assign a set of correct target layers to a drag layer.
function DDH_setCorrectTargets(dragLayerNumber)
{
	if (DDH_setCorrectTargets.arguments.length < 2)
	{
		alert("The function DDH_setCorrectTargets(dragLayerNumber *[,dropTargetNumber]) requires 2 or more arguments!");
		return;
	}
	 
	// First Clear all evalMask entries.
	for (var t=0;t<dragItemArray[dragLayerNumber-1].targets.length;t++)
	{
		dragItemArray[dragLayerNumber-1].evalMask[t] = false;
	}

	// Set only those evalMask entries that need to be set.
	for (var i=1;i<DDH_setCorrectTargets.arguments.length;i++)
	{
		for (var t=0;t<dragItemArray[dragLayerNumber-1].targets.length;t++)
		{
			if (dragItemArray[dragLayerNumber-1].targets[t] == dropTargetArray[DDH_setCorrectTargets.arguments[i]-1])
			{
				dragItemArray[dragLayerNumber-1].evalMask[t] = true;
			}
		}
	}
	
}

// Enable multidrop for a set of drop targets.
function DDH_enableMultiDrops()
{
	if (DDH_enableMultiDrops.arguments.length < 1)
	{
		alert("The function DDH_enableMultiDrops(+dropTargetNumber) requires 1 or more arguments!");
		return;
	}
	
	for (var i=0;i<DDH_enableMultiDrops.arguments.length;i++)
	{
		dropTargetArray[DDH_enableMultiDrops.arguments[i]-1].multiDropEnabled = true;
	}
}

// Disable multidrop for a set of drop targets.
function DDH_disableMultiDrops()
{
	if (DDH_disableMultiDrops.arguments.length < 1)
	{
		alert("The function DDH_disableMultiDrops(+dropTargetNumber) requires 1 or more arguments!");
		return;
	}
	
	for (var i=0;i<DDH_disableMultiDrops.arguments.length;i++)
	{
		dropTargetArray[DDH_disableMultiDrops.arguments[i]-1].multiDropEnabled = false;
	}
}

// Disable a drag item.
function DDH_disableDragItem(dragLayerNumber)
{
	if (DDH_disableDragItem.arguments.length != 1)
	{
		alert("The function DDH_disableDragItem(dragLayerNumber) requires 1 argument!");
		return;
	}
	
	DDH_disableDragItems(dragLayerNumber);
}

// Disable drag items.
function DDH_disableDragItems()
{
	if (DDH_disableDragItems.arguments.length < 1)
	{
		alert("The function DDH_disableDragItems(+dragLayerNumber) requires 1 or more arguments!");
		return;
	}
	
	for (var i=0;i<DDH_disableDragItems.arguments.length;i++)
	{
		disableDrag(dragItemArray[DDH_disableDragItems.arguments[i]-1]);
	}
}

// Enable a drag item.
function DDH_enableDragItem(dragLayerNumber)
{
	if (DDH_enableDragItem.arguments.length != 1)
	{
		alert("The function DDH_enableDragItem(dragLayerNumber) requires 1 argument!");
		return;
	}
	
	DDH_enableDragItems(dragLayerNumber);
}

// Enable drag items.
function DDH_enableDragItems(dragLayerNumber)
{
	if (DDH_enableDragItems.arguments.length < 1)
	{
		alert("The function DDH_enableDragItems(+dragLayerNumber) requires 1 or more arguments!");
		return;
	}
	
	for (var i=0;i<DDH_enableDragItems.arguments.length;i++)
	{
		enableDrag(dragItemArray[DDH_enableDragItems.arguments[i]-1]);
	}
}

// Determines the number of drag items currently
// residing on drop targets.
function DDH_numItemsDropped()
{
	var count = 0;
	for (var i=0;i<dragItemArray.length;i++)
	{
		if ( DDH_dragItemIsDropped(i+1) )
		{
			count++;
		}
	}
	return count;
}

// Determines whether or not a drag item has been dropped
// on a drop target.
function DDH_dragItemIsDropped(dragLayerNumber)
{
	if (dragItemArray[dragLayerNumber-1].occupies != null)
	{
		return true;
	}
	return false;
}

// Determines whether or not a drag item occupies
// a correct drop target.
function DDH_dragItemIsCorrect(dragLayerNumber)
{
	if (dragItemArray[dragLayerNumber-1].occupies != null)
	{
		for (var i=0;i<dragItemArray[dragLayerNumber-1].evalMask.length;i++)
		{
			if (dragItemArray[dragLayerNumber-1].evalMask[i] && (dragItemArray[dragLayerNumber-1].targets[i] == dragItemArray[dragLayerNumber-1].occupies))
			{
				return true;
			}
		}
	}
	return false;
}

// Find out how many drag items a drop target holds.
function DDH_dropTargetOccupiedCount(dropTargetNumber)
{
	var count = 0;
	// for each occupier
	for (var i=0;i<dropTargetArray[dropTargetNumber-1].occupiers.length;i++)
	{	// for each index
		if (dropTargetArray[dropTargetNumber-1].occupiers[i] != null)
		{
			count++;
		}
	}
	return count;
}

function DDH_dropTargetIsOccupied(dropTargetNumber)
{
	return (DDH_dropTargetOccupiedCount(dropTargetNumber) > 0);
}

// Find out if a drop target holds a correct drag item.
// Returns false if an incorrect drag item is found to be
// occupying the drop target.  Only returns true if no
// incorrect drag items are occupying the drop target,
// and atleast one correct drag item is found occupying
// the drop target.
function DDH_dropTargetIsCorrect(dropTargetNumber)
{
	var wrongDropFlag = false;
	var correctDropFlag = false;

	// for each occupier
	for (var i=0;i<dropTargetArray[dropTargetNumber-1].occupiers.length;i++)
	{	// for each index
		if (dropTargetArray[dropTargetNumber-1].occupiers[i] != null)
		{
			for (var t=0;t<dropTargetArray[dropTargetNumber-1].occupiers[i].evalMask.length;t++)
			{
				if (!dropTargetArray[dropTargetNumber-1].occupiers[i].evalMask[t] && (dropTargetArray[dropTargetNumber-1] == dropTargetArray[dropTargetNumber-1].occupiers[i].targets[t]))
				{
					wrongDropFlag = true;;
				}
				if (dropTargetArray[dropTargetNumber-1].occupiers[i].evalMask[t] && (dropTargetArray[dropTargetNumber-1] == dropTargetArray[dropTargetNumber-1].occupiers[i].targets[t]))
				{
					correctDropFlag = true;;
				}
			}
		}
	}
	if (correctDropFlag && !wrongDropFlag)
	{
		return true;
	}
	return false;
}

// Reset a drag item by moving it back to its origin.
function DDH_resetDragItems(DragItemNumber)
{
	if (DDH_resetDragItems.arguments.length < 1)
	{
		alert("The function DDH_resetDragItems(+dropTargetNumber) requires 1 or more arguments!");
		return;
	}
	
	for (var i=0;i<DDH_resetDragItems.arguments.length;i++)
	{
		resetDragItem(dragItemArray[DragItemNumber-1]);
	}
}

// Snap a drag layer back to its original position.
function DDH_snapToOrigin(DragItemNumber)
{
	var occupies = dragItemArray[DragItemNumber-1].occupies;
	
	DDH_resetDragItems(DragItemNumber);

	if (occupies != null && !occupies.multiDropEnabled && !disabledDropTargetArray[DDH_getLayerNumber(occupies)-1]) 
	{
		occupies.enabled = true;
	}
}

// Disable a drop target.
function DDH_disableDropTarget(DropTargetNumber)
{
	if (DDH_disableDropTarget.arguments.length != 1)
	{
		alert("The function DDH_disableDropTarget(DropTargetNumber) requires 1 argument!");
		return;
	}
	DDH_disableDropTargets(DropTargetNumber);
}

// Disable drop targets (They will no longer act
// as a valid landing areas).
function DDH_disableDropTargets()
{
	if (DDH_disableDropTargets.arguments.length < 1)
	{
		alert("The function DDH_disableDropTargets(+DropTargetNumber) requires atleast 1 argument!");
		return;
	}
	for (var i=0;i<DDH_disableDropTargets.arguments.length;i++)
	{
		var DropTargetNumber = DDH_disableDropTargets.arguments[i];
		dropTargetArray[DropTargetNumber-1].enabled = false;
		disabledDropTargetArray[DropTargetNumber-1] = true;
	}
}

// Enable a drop target.
function DDH_enableDropTarget(DropTargetNumber)
{
	if (DDH_enableDropTarget.arguments.length != 1)
	{
		alert("The function DDH_enableDropTarget(DropTargetNumber) requires 1 argument!");
		return;
	}
	DDH_enableDropTargets(DropTargetNumber);
}

// Enable drop targets (They will now act
// as a valid landing areas).
function DDH_enableDropTargets()
{
	if (DDH_enableDropTargets.arguments.length < 1)
	{
		alert("The function DDH_enableDropTargets(+DropTargetNumber) requires atleast 1 argument!");
		return;
	}
	for (var i=0;i<DDH_enableDropTargets.arguments.length;i++)
	{
		var DropTargetNumber = DDH_enableDropTargets.arguments[i];
		dropTargetArray[DropTargetNumber-1].enabled = true;
		disabledDropTargetArray[DropTargetNumber-1] = false;
	}
}

// Returns the layer number for a specified
// dropTarget or dragItem object.
function DDH_getLayerNumber(objRef)
{
	if (DDH_getLayerNumber.arguments.length != 1)
	{
		alert("The function DDH_getLayerNumber(objRef) requires 1 argument!");
		return null;
	}
	var id = objRef.layerRef.id;
	if (id.slice(0,9) == "DragLayer")
	{
		return parseInt(id.slice(9,id.length));
	}
	else if (id.slice(0,10) == "DropTarget")
	{
		return parseInt(id.slice(10,id.length));
	}
	return null;
}

// Place the specified drag item on the specified
// drop target.  If parameter evaluateFlag is
// true, then the drag operation will be evaluated
// just as it would be if the user had dragged it
// himself - otherwise no checks are done to evaluate
// whether or not the drag was valid.
function DDH_dragToTarget(dragItemNumber, dropTargetNumber, evaluateFlag)
{	
	var previousTarget = dragItemArray[dragItemNumber-1].occupies;
	
	moveLayer(dragItemArray[dragItemNumber-1].layerRef, getLayerX(dropTargetArray[dropTargetNumber-1].layerRef), getLayerY(dropTargetArray[dropTargetNumber-1].layerRef));
	dragItemArray[dragItemNumber-1].occupies = dropTargetArray[dropTargetNumber-1];
	
	//If multiDropEnabled is not true, then set only the first array entry in the occupiers array
	if(!dropTargetArray[dropTargetNumber-1].multiDropEnabled)
		dropTargetArray[dropTargetNumber-1].occupiers[0] = dragItemArray[dragItemNumber-1];
	else
	{
		//Set the next available occupiers entry
		dropTargetArray[dropTargetNumber-1].occupiers[dropTargetArray[dropTargetNumber-1].occupiers.length] = dragItemArray[dragItemNumber-1];
	}
	
	if (!dropTargetArray[dropTargetNumber-1].multiDropEnabled) 
	{
		dropTargetArray[dropTargetNumber-1].enabled = false;
	}
	if (previousTarget != null && !previousTarget.multiDropEnabled && !disabledDropTargetArray[DDH_getLayerNumber(previousTarget)-1]) 
	{
		previousTarget.enabled = true;
	}

	DDH_lastItemDragged = dragItemNumber;
	DDH_lastTargetHit = dropTargetNumber;

	if (evaluateFlag == true)
	{
		checkDrop("DragLayer" + dragItemNumber);
	}
}

function DDH_checkDrop(dragItemNumber)
{
	checkDrop("DragLayer" + dragItemNumber);
}

function DDH_SetFrameDimensions(width, height)
{
	screenExtentX = width;
	screenExtentY = height;
}
	
function DDH_getOccupiers(dropTargetNumber)
{
	var temp = new Array();
	var counter = 0;
	
	for (var i=0;i<dropTargetArray[dropTargetNumber-1].occupiers.length;i++)
	{
		if (dropTargetArray[dropTargetNumber-1].occupiers[i] != null)
		{
			temp[counter++] = DDH_getLayerNumber(dropTargetArray[dropTargetNumber-1].occupiers[i]);
		}
	}
	
	return temp.toString();
}

function DDH_getOccupies(dragItemNumber)
{
	if (dragItemArray[dragItemNumber-1].occupies == null)
	{
		return null;
	}
	else
	{
		return DDH_getLayerNumber(dragItemArray[dragItemNumber-1].occupies);
	}
}

